﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace Lilium.LParse
{
    public static class TextLabels
    {
        public static IEnumerable<object> GetExceptedCategory(UnicodeCategory category)
        {
            yield return "unicode category " + GetUnicodeClassDesignation(category);
        }

        public static IEnumerable<object> GetExceptedCategories(params UnicodeCategory[] categories)
        {
            var l = categories.Length - 1;
            if (l > 0)
            {
                var sb = new StringBuilder("unicode category ");
                sb.Append(GetUnicodeClassDesignation(categories[0]));
                for (int i = 1; i < l; i++)
                    sb.Append(", ").Append(GetUnicodeClassDesignation(categories[i]));
                yield return sb.Append(" or ").Append(GetUnicodeClassDesignation(categories[l])).ToString();
            }
            else if (l == 0)
                yield return "unicode category " + GetUnicodeClassDesignation(categories[0]);
        }

        public static IEnumerable<object> GetExceptedChars(string chars)
        {
            foreach (var ch in chars)
                yield return ch;
        }

        public static IEnumerable<object> GetExceptedChars(char lower, char upper)
        {
            while (lower <= upper)
            {
                yield return lower;
                lower++;
            }
        }

        public static IEnumerable<object> GetNoneOfExceptedChars(string chars)
        {
            var l = chars.Length - 1;
            if (l > 0)
            {
                var sb = new StringBuilder("none of ");
                sb.Append(chars[0]);
                for (int i = 1; i < l; i++)
                    sb.Append(", ").Append(chars[i]);
                yield return sb.Append(" or ").Append(chars[l]).ToString();
            }
            else if (l == 0)
                yield return "not " + chars[0];
        }

        public static string GetUnicodeClassDesignation(UnicodeCategory category)
        {
            switch (category)
            {
                case UnicodeCategory.UppercaseLetter: return "Lu";
                case UnicodeCategory.LowercaseLetter: return "Ll";
                case UnicodeCategory.TitlecaseLetter: return "Lt";
                case UnicodeCategory.ModifierLetter: return "Lm";
                case UnicodeCategory.OtherLetter: return "Lo";
                case UnicodeCategory.NonSpacingMark: return "Mn";
                case UnicodeCategory.SpacingCombiningMark: return "Mc";
                case UnicodeCategory.EnclosingMark: return "Me";
                case UnicodeCategory.DecimalDigitNumber: return "Nd";
                case UnicodeCategory.LetterNumber: return "Nl";
                case UnicodeCategory.OtherNumber: return "No";
                case UnicodeCategory.SpaceSeparator: return "Zs";
                case UnicodeCategory.LineSeparator: return "Zl";
                case UnicodeCategory.ParagraphSeparator: return "Zp";
                case UnicodeCategory.Control: return "Cc";
                case UnicodeCategory.Format: return "Cf";
                case UnicodeCategory.Surrogate: return "Cs";
                case UnicodeCategory.PrivateUse: return "Co";
                case UnicodeCategory.ConnectorPunctuation: return "Pc";
                case UnicodeCategory.DashPunctuation: return "Pd";
                case UnicodeCategory.OpenPunctuation: return "Ps";
                case UnicodeCategory.ClosePunctuation: return "Pe";
                case UnicodeCategory.InitialQuotePunctuation: return "Pi";
                case UnicodeCategory.FinalQuotePunctuation: return "Pf";
                case UnicodeCategory.OtherPunctuation: return "Po";
                case UnicodeCategory.MathSymbol: return "Sm";
                case UnicodeCategory.CurrencySymbol: return "Sc";
                case UnicodeCategory.ModifierSymbol: return "Sk";
                case UnicodeCategory.OtherSymbol: return "So";
                case UnicodeCategory.OtherNotAssigned: return "Cn";
                default: throw new ArgumentOutOfRangeException("category", string.Format("Unable to determine unicode designation for symbol category {0}", category));
            }
        }
    }
}